s2_220128_qc_integration

nlc

9/14/2021

Experiment & contact info

PIs: Rosalie Sears (), Laura Heiser ()

Sample preparation: Zinab Doha ()

Library prep from single cells: Xi Li & Colin Daniel ()

Analysis: Nick Calistri ()

Sequencing performed by OHSU MPSSR

Analysis design

  • load so_list.rds

  • combine all libraries into so_merge

  • process so_merge like normal (dimred & clustering)

  • Compute qc metrics and calculate cellcycle score

  • Analyze doublet calls vs cluster id to see if any clusters are majority doublet

  • Filter based on QC metrics and sample ID

  • integrate experiments with rLiger

  • save integrated so_merge as .rds file

Set up

Load libraries

library(Matrix)
library(tidyverse)
## -- Attaching packages --------------------------------------- tidyverse 1.3.1 --
## v ggplot2 3.3.5     v purrr   0.3.4
## v tibble  3.1.6     v dplyr   1.0.8
## v tidyr   1.2.0     v stringr 1.4.0
## v readr   2.1.2     v forcats 0.5.1
## Warning: package 'tibble' was built under R version 4.1.2
## Warning: package 'tidyr' was built under R version 4.1.2
## Warning: package 'readr' was built under R version 4.1.2
## Warning: package 'dplyr' was built under R version 4.1.2
## -- Conflicts ------------------------------------------ tidyverse_conflicts() --
## x tidyr::expand() masks Matrix::expand()
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
## x tidyr::pack()   masks Matrix::pack()
## x tidyr::unpack() masks Matrix::unpack()
library(Seurat)
## Warning: package 'Seurat' was built under R version 4.1.2
## Registered S3 method overwritten by 'spatstat.geom':
##   method     from
##   print.boxx cli
## Attaching SeuratObject
library(rliger)
## Loading required package: cowplot
## Loading required package: patchwork
## 
## Attaching package: 'patchwork'
## The following object is masked from 'package:cowplot':
## 
##     align_plots
library(SeuratWrappers)
library(ggalluvial)
library(harmony)
## Loading required package: Rcpp

load s1_so_list.rds

so_list <- readRDS('analysis_files/s1_seurat_list.rds')

Mouse/tumor stats from README metadata file

# Read in readme with HTO and tumor ID
lib_meta <- read_csv('original_data/README.csv')
## Rows: 78 Columns: 12
## -- Column specification --------------------------------------------------------
## Delimiter: ","
## chr (11): exa_dir, mpssr_seq_run_name, mpssr_library_name, library_suffix, c...
## lgl  (1): feature_barcodes
## 
## i Use `spec()` to retrieve the full column specification for this data.
## i Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Add the run_library variable
lib_meta <- lib_meta %>%
  mutate(run_library = paste0(mpssr_seq_run_name,
                              '_',
                              mpssr_library_name,
                              str_replace_na(library_suffix, replacement = '')))

lib_meta$mouse_id <- str_split(lib_meta$condition_string, pattern = '_', simplify = TRUE)[,1]

lib_meta$phenotype <- str_replace(lib_meta$mouse_id, pattern = "[:digit:]+", "")

tumor_histology_dict <- lib_meta %>%
  dplyr::select(condition_string, histology) %>%
  distinct()

Merge data and visualize QC metrics

Merge seurat objects (no integration, simple appending), filter to only SR & SP assigned tumors and add metadata

so_merge <- merge(x = so_list[[1]], y = unlist(so_list)[-1])
## Warning in CheckDuplicateCellNames(object.list = objects): Some cell names are
## duplicated across objects provided. Renaming to enforce unique cell names.
# Add metadata: percent.mt, phenotype (from tumor ID)
so_merge[['percent.mt']] <- PercentageFeatureSet(so_merge, pattern = '^mt-')

so_merge[['percent.ribo']] <- PercentageFeatureSet(so_merge, pattern = '^Rp[sl][[:digit:]]')

so_merge[['phenotype']] <- str_replace(str_split(so_merge@meta.data$tumor,
                                                 pattern = '_',
                                                 simplify = TRUE)[,1],
                                       '[:digit:]+',
                                       '')

so_merge[['mouse']] <- str_split(so_merge@meta.data$tumor,
                    pattern = '_',
                    simplify = TRUE)[,1]

so_merge[['histology']] <- plyr::mapvalues(x = so_merge@meta.data$tumor,
                                           from = tumor_histology_dict$condition_string,
                                           to = tumor_histology_dict$histology)
## The following `from` values were not present in `x`: S8_T2, S9_T1, S9_T2, R4_T1, R4_T2, R4_T3, R5_T1, R5_T2, R5_T3, S8_T1, PD1_T1, PD2_T1, PD3_T1, PD4_T1, PD5_T1, PD6_T1
# Filter anything not assigned SP or SR status
table(so_merge@meta.data$histology)
## 
##  Doublet Negative       SP       SR 
##    74023    36538     4003    13632
so_merge <- subset(so_merge, subset = histology %in% c('SR', 'SP'))

Visualize QC metrics

# QC plots
FeatureScatter(so_merge, feature1 = 'nFeature_RNA', feature2 = 'nCount_RNA', group.by = 'library_id')+
  geom_vline(xintercept = 250)

FeatureScatter(so_merge, feature1 = 'percent.mt', feature2 = 'percent.ribo', group.by = 'library_id')

qc_features <- c('nFeature_RNA', 'nCount_RNA', 'nCount_HTO', 'percent.mt', 'percent.ribo')

for(i in qc_features){
  p1 <- VlnPlot(so_merge,
                features = i,
                group.by = 'library_id',
                pt.size = 0)+
    theme(legend.position = 'none')
  print(p1)
}

# What is our breakdown between library ID and HTO demultiplexed tumor ID
freq_table_og <- so_merge@meta.data %>%
  dplyr::select(library_id, tumor) %>%
  table()

pheatmap::pheatmap(freq_table_og,
                   display_numbers = freq_table_og,
                   main = 'Cell counts before QC')

og_counts <- tibble(tumor = colnames(freq_table_og),
                      count = colSums(freq_table_og),
                      fraction = colSums(freq_table_og)/sum(freq_table_og))

knitr::kable(og_counts)
tumor count fraction
V3_T1 1710 0.0969663
V3_T2 797 0.0451942
V4 621 0.0352141
V5 1238 0.0702013
V6_T1 1418 0.0804083
V6_T2 6560 0.3719875
V6_T3 965 0.0547207
V7_T1 1008 0.0571591
V7_T2 1036 0.0587468
V7_T3 1407 0.0797845
V8_T1 875 0.0496172
so_noqc_meta <- so_merge@meta.data

QC plots for supplement

# Individual feature plots
## 720x540 output scaled to 2"

ggplot(so_merge@meta.data, aes(x = tumor, y = log10(nCount_RNA), fill = tumor))+
  geom_boxplot()+
  theme_bw()+
  ggtitle('Number of UMIs per cell')

ggplot(so_merge@meta.data, aes(x = tumor, y = nFeature_RNA, fill = tumor))+
  geom_boxplot()+
  theme_bw()+
  geom_hline(yintercept = 250, linetype = 'dashed')+
  ggtitle('Number of unique features (genes) per cell')

ggplot(so_merge@meta.data, aes(x = tumor, y = percent.mt, fill = tumor))+
  geom_boxplot()+
  theme_bw()+
  geom_hline(yintercept = 25, linetype = 'dashed')+
  ggtitle('Percent mitochondrial reads')

# removal criteria
## 720x540 scaled to 2"

ggplot(so_merge@meta.data, aes(x = tumor, fill = DF.classifications))+
  geom_bar(position = 'dodge')+
  theme_bw()

ggplot(so_merge@meta.data, aes(x = tumor, fill = nFeature_RNA > 250))+
  geom_bar(position = 'dodge')+
  theme_bw()

ggplot(so_merge@meta.data, aes(x = tumor, fill = percent.mt < 25))+
  geom_bar(position = 'dodge')+
  theme_bw()

Trim data based on QC metrics

# Subset based on nFeatureRNA > 250 and percent.mt < 25

FeatureScatter(so_merge,
               feature1 = 'nFeature_RNA',
               feature2 = 'percent.mt',
               group.by = 'library_id')+
  geom_vline(xintercept = 250)+
  geom_hline(yintercept = 25)

ggplot(so_merge@meta.data, aes(x = nFeature_RNA, y = percent.mt, color = tumor))+
  geom_point()+
  facet_grid(DF.classifications~library_id)+
  theme_bw()

meta_filtered <- so_merge@meta.data %>%
  filter(nFeature_RNA > 250) %>%
  filter(percent.mt < 25) %>%
  filter(DF.classifications == 'Singlet')

so_trimmed <- subset(so_merge,
                     cells = row.names(so_merge@meta.data)[! row.names(so_merge@meta.data) %in% row.names(meta_filtered)])

so_merge <- subset(so_merge,
                   cells = row.names(meta_filtered))

# Look at what is left
freq_table <- so_merge@meta.data %>%
  dplyr::select(library_id, tumor) %>%
  table()

pheatmap::pheatmap(freq_table,
                   display_numbers = freq_table,
                   main = 'Cell counts after QC')

new_counts <- tibble(tumor = colnames(freq_table),
                      count = colSums(freq_table),
                      fraction = colSums(freq_table)/sum(freq_table))

qc_counts <- full_join(x = og_counts,
                       y = new_counts,
                       by = 'tumor',
                       suffix = c('.og', '.qc'))

qc_counts <- qc_counts %>%
  dplyr::select(-fraction.og, -fraction.qc) %>%
  mutate(count.removed = count.og - count.qc) %>%
  mutate(fraction.remain = count.qc/count.og)

knitr::kable(qc_counts)
tumor count.og count.qc count.removed fraction.remain
V3_T1 1710 1428 282 0.8350877
V3_T2 797 614 183 0.7703890
V4 621 490 131 0.7890499
V5 1238 895 343 0.7229402
V6_T1 1418 700 718 0.4936530
V6_T2 6560 5995 565 0.9138720
V6_T3 965 578 387 0.5989637
V7_T1 1008 742 266 0.7361111
V7_T2 1036 648 388 0.6254826
V7_T3 1407 1138 269 0.8088131
V8_T1 875 814 61 0.9302857
## Alluvial plot of library/mouse/tumor
meta_alluvial <- so_merge@meta.data %>%
  group_by(library_id, phenotype, mouse, tumor, HTO_classification.global, histology) %>%
  summarize(n_cells = n())
## `summarise()` has grouped output by 'library_id', 'phenotype', 'mouse',
## 'tumor', 'HTO_classification.global'. You can override using the `.groups`
## argument.
ggplot(meta_alluvial, aes(y = n_cells, axis1 = library_id, axis2 = mouse, axis3 = tumor, axis4 = histology, fill = histology))+
  geom_alluvium()+
  geom_stratum()+
  geom_label(stat = "stratum", aes(label = after_stat(stratum)))+
  theme_minimal()+
  scale_x_discrete(limits = c('library', 'mouse', 'tumor', 'histology'))
## Warning in to_lodes_form(data = data, axes = axis_ind, discern =
## params$discern): Some strata appear at multiple axes.

## Warning in to_lodes_form(data = data, axes = axis_ind, discern =
## params$discern): Some strata appear at multiple axes.

## Warning in to_lodes_form(data = data, axes = axis_ind, discern =
## params$discern): Some strata appear at multiple axes.

# Sample breakdown

sample_stats <- so_merge@meta.data %>%
  group_by(histology) %>%
  dplyr::select(histology, tumor) %>%
  table()

Visualize what was removed (excluding doublets)

so_trimmed <- FindVariableFeatures(so_trimmed)
so_trimmed <- NormalizeData(so_trimmed)
so_trimmed <- ScaleData(so_trimmed)
## Centering and scaling data matrix
so_trimmed <- RunPCA(so_trimmed)
## PC_ 1 
## Positive:  Ppp1r14b, Hsp90aa1, Prdx1, Anxa2, S100a6, Anxa1, Hspd1, Mgst1, Dstn, Dbi 
##     Tubb4b, H2afz, Zfand5, Morf4l2, Klf4, Nhp2, Prdx5, Prdx6, Bst2, Mt1 
##     Ier3, S100a16, Ctsl, Cyc1, Rbp1, Ube2s, Mrpl34, Epcam, Tpm1, Tnfrsf12a 
## Negative:  Igkc, Cd74, Hba-a1, Hbb-bs, H2-Aa, Apoe, Igha, H2-Ab1, C1qa, Lyz2 
##     C1qb, Ctss, Tyrobp, Wfdc17, S100a9, C1qc, Ms4a7, Ccl12, S100a8, Retnlg 
##     Retnla, Wfdc21, Aif1, Stfa2l1, Lst1, Ccl6, Cstdc4, Ifitm6, Clec4d, Il1b 
## PC_ 2 
## Positive:  Col3a1, Col1a2, Adamts5, Fn1, Sparc, Abi3bp, Nid1, Rarres2, Col1a1, C4b 
##     Mfap5, Clec3b, Ogn, C3, Col14a1, Cd248, Prss23, Cxcl12, Tnxb, Igf1 
##     Svep1, Ctsk, Eln, Fndc1, Thbs2, Efemp1, Serpina3n, Igfbp7, Ebf1, Cd34 
## Negative:  Epcam, Krt8, Cldn3, Krt18, Stmn1, Cldn7, Cldn4, Cdh1, Pclaf, Car2 
##     Hist1h1b, Plet1, Hist1h3c, Birc5, Ltf, Tacstd2, Mki67, Rrm2, Rab25, Top2a 
##     Hmgb2, Krt19, S100a14, Fxyd3, Bspry, Kif11, Wfdc18, Elf5, Spc24, Cdca8 
## PC_ 3 
## Positive:  Nkg7, Xcl1, Cd7, Klra5, Hist1h1b, Il2rb, Ctsw, Hist1h3c, Ptprcap, Gzmb 
##     Top2a, Skap1, Pclaf, Cd226, Gimap4, Hist1h3e, Hist1h4d, Hist1h1a, Gm19585, Smc2 
##     Mki67, Fbxo5, Kif11, Kif15, Hist1h2bm, Sla2, Hist1h2af, Inpp4b, Hist2h2bb, Coro1a 
## Negative:  S100a14, Cldn3, Krt8, Cldn4, Krt18, Tacstd2, 2200002D01Rik, Clu, Epcam, Cldn7 
##     Krt19, Ltf, Fxyd3, Hspb1, Lgals7, Sprr2a3, Rab25, Wfdc18, Plet1, Krt7 
##     Asprv1, Klf5, Cystm1, Arg1, Gjb2, Gm41386, Stra6, Ovol1, Elf3, Klk10 
## PC_ 4 
## Positive:  Pcolce2, Tnxb, Cd34, Opcml, Clec3b, Efemp1, Dpp4, Pi16, Igfbp6, Ly6c1 
##     Efhd1, Itih5, Heg1, Cmah, Pla1a, Lrrn4cl, Cadm3, Ebf2, Ccl11, Sema3c 
##     Pamr1, Scara5, Ifi205, Slfn5, Tppp3, Dpt, Anxa3, Mfap5, Ace, Pcsk6 
## Negative:  Slc7a2, Ecrg4, Mme, Mgp, Edil3, Il17b, Gpm6b, Ptn, Matn2, Smoc1 
##     Ndufa4l2, Col11a1, Serpine2, Spp1, Mmp3, Ank, Enpp1, Cox4i2, Col8a1, Tnfrsf21 
##     Spon1, Nrxn1, Vcam1, Ptgfr, Gas1, Col4a2, Cx3cl1, Tgfb2, Thsd7a, Igfbp2 
## PC_ 5 
## Positive:  Rrm2, Birc5, Prc1, Top2a, Pclaf, Hist1h3c, Hist1h1b, Nusap1, Cdk1, Cdca8 
##     Cenpw, Smc2, Esco2, Sgo1, Cdca3, Kif11, Ube2c, Ccnb2, Ccna2, Klra5 
##     Stmn1, Gzmb, Pcolce2, Itih5, Hmmr, Racgap1, Tpx2, Xcl1, Spc24, Diaph3 
## Negative:  Cd14, Il1b, Cxcl2, Ccrl2, Plek, Nlrp3, Clec4e, Clec4d, S100a9, Lilrb4a 
##     Acod1, S100a8, Lilr4b, Samsn1, Ccr1, Il1rn, Ifitm1, G0s2, Wfdc17, Alox5ap 
##     Mxd1, Slc7a11, Slc15a3, Hdc, Fcer1g, Trem1, Stfa2l1, Tyrobp, Spi1, Hcar2
ElbowPlot(so_trimmed)

so_trimmed <- RunUMAP(so_trimmed, dims = 1:10)
## Warning: The default method for RunUMAP has changed from calling Python UMAP via reticulate to the R-native UWOT using the cosine metric
## To use Python UMAP via reticulate, set umap.method to 'umap-learn' and metric to 'correlation'
## This message will be shown once per session
## 22:08:42 UMAP embedding parameters a = 0.9922 b = 1.112
## 22:08:42 Read 3593 rows and found 10 numeric columns
## 22:08:42 Using Annoy for neighbor search, n_neighbors = 30
## 22:08:42 Building Annoy index with metric = cosine, n_trees = 50
## 0%   10   20   30   40   50   60   70   80   90   100%
## [----|----|----|----|----|----|----|----|----|----|
## **************************************************|
## 22:08:43 Writing NN index file to temp file C:\Users\Nick\AppData\Local\Temp\RtmpmcWjm4\filec805e945b6c
## 22:08:43 Searching Annoy index using 1 thread, search_k = 3000
## 22:08:44 Annoy recall = 100%
## 22:08:44 Commencing smooth kNN distance calibration using 1 thread
## 22:08:44 9 smooth knn distance failures
## 22:08:45 Initializing from normalized Laplacian + noise
## 22:08:45 Commencing optimization for 500 epochs, with 150984 positive edges
## 22:08:53 Optimization finished
DimPlot(so_trimmed, group.by = 'phenotype')+
  coord_equal()

FeaturePlot(so_trimmed,
            features = c('nCount_RNA', 'nFeature_RNA', 'percent.mt', 'Hba-a1'),
            coord.fixed = TRUE)

FeaturePlot(so_trimmed,
            features = c('percent.mt', 'Hba-a1', 'Ptprc', 'Epcam'),
            coord.fixed = TRUE)

Remove old seurat objects/lists and run GC

so_trimmed <- NULL
so_list <- NULL
gc()
##            used  (Mb) gc trigger    (Mb)   max used    (Mb)
## Ncells  3555951 190.0    6325171   337.9    6325171   337.9
## Vcells 58623460 447.3 2153601279 16430.7 2677994074 20431.5

QC stats table for supplement

# Stats table

so_tumor_stats <- so_merge@meta.data %>%
  group_by(tumor) %>%
  summarize(nCells = n(),
            mean_nCount_RNA = mean(nCount_RNA),
            mean_nFeature_RNA = mean(nFeature_RNA),
            mean_percent.mt = mean(percent.mt)) 

so_tumor_stats %>%
  DT::datatable()
# Statistics used in results text

## Number of tumors
length(unique(so_merge@meta.data$tumor))
## [1] 11
## Number of mice
length(unique(so_merge@meta.data$mouse))
## [1] 6
## Number of unique libraries
length(unique(so_merge@meta.data$library_id))
## [1] 10
## Mean and range number of cells per tumor
range(so_tumor_stats$nCells)
## [1]  490 5995
sum(so_tumor_stats$nCells)
## [1] 14042
## Mean genes per cell
mean(so_merge@meta.data$nFeature_RNA)
## [1] 1198.225
mean(so_merge@meta.data$nCount_RNA)
## [1] 3394.431

Integration with rliger and harmony (runs both)

if(file.exists('analysis_files/s2_vehicle_integrated.rds')){
  print('Loading existing s2_vehicle_integrated.rds file')
  so_merge <- readRDS('analysis_files/s2_vehicle_integrated.rds')
}else{
  print('so_merge_rliger.rds file not found.')
  print('Processing iNMF integration, 200k cells ~= 1 hour')
  
  #iNMF integration with rliger
  so_merge <- NormalizeData(so_merge)
  so_merge <- FindVariableFeatures(so_merge)
  so_merge <- ScaleData(so_merge,
                        split.by = 'library_id',
                        do.center = FALSE)
  
  so_merge <- RunOptimizeALS(so_merge,
                             k = 50,
                             lambda = 5,
                             split.by = 'library_id',
                             nrep = 5)
  
  so_merge <- RunQuantileNorm(so_merge,
                              split.by = 'library_id')
  
  # UMAP
  so_merge <- RunUMAP(so_merge,
                      dims = 1:ncol(so_merge[['iNMF']]),
                      reduction = 'iNMF')  
  
  # Harmony integration
  so_merge <- RunPCA(so_merge)
  
  so_merge <- RunHarmony(so_merge, 
                       group.by.vars = 'library_id',
                       plot_convergence = TRUE,
                       max.iter.harmony = 20)
  
  
  # Save output
  saveRDS(so_merge, file = 'analysis_files/s2_vehicle_integrated.rds')
}
## [1] "Loading existing s2_vehicle_integrated.rds file"

UMAP assessment of iNMF integration

DimPlot(so_merge,
        label = TRUE,
        group.by = 'library_id')+
  coord_equal()

DimPlot(so_merge,
        label = TRUE,
        group.by = 'library_id')+
  coord_equal()+
  facet_wrap(~library_id)

DimPlot(so_merge,
        label = TRUE,
        group.by = 'histology')+
  coord_equal()

DimPlot(so_merge,
        label = TRUE,
        group.by = 'histology')+
  coord_equal()+
  facet_wrap(~histology)

DimPlot(so_merge,
        label = TRUE,
        group.by = 'tumor')+
  coord_equal()

DimPlot(so_merge,
        label = TRUE,
        group.by = 'tumor')+
  coord_equal()+
  facet_wrap(~tumor)

sessionInfo()

sessionInfo()
## R version 4.1.1 (2021-08-10)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 10 x64 (build 19044)
## 
## Matrix products: default
## 
## locale:
## [1] LC_COLLATE=English_United States.1252 
## [2] LC_CTYPE=English_United States.1252   
## [3] LC_MONETARY=English_United States.1252
## [4] LC_NUMERIC=C                          
## [5] LC_TIME=English_United States.1252    
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] harmony_0.1.0        Rcpp_1.0.7           ggalluvial_0.12.3   
##  [4] SeuratWrappers_0.3.0 rliger_1.0.0         patchwork_1.1.1     
##  [7] cowplot_1.1.1        SeuratObject_4.0.4   Seurat_4.1.0        
## [10] forcats_0.5.1        stringr_1.4.0        dplyr_1.0.8         
## [13] purrr_0.3.4          readr_2.1.2          tidyr_1.2.0         
## [16] tibble_3.1.6         ggplot2_3.3.5        tidyverse_1.3.1     
## [19] Matrix_1.3-4        
## 
## loaded via a namespace (and not attached):
##   [1] readxl_1.3.1          backports_1.3.0       plyr_1.8.6           
##   [4] igraph_1.2.7          lazyeval_0.2.2        splines_4.1.1        
##   [7] crosstalk_1.2.0       listenv_0.8.0         scattermore_0.8      
##  [10] digest_0.6.27         foreach_1.5.2         htmltools_0.5.2      
##  [13] fansi_1.0.2           magrittr_2.0.1        tensor_1.5           
##  [16] cluster_2.1.2         doParallel_1.0.17     ROCR_1.0-11          
##  [19] remotes_2.4.2         tzdb_0.2.0            globals_0.14.0       
##  [22] modelr_0.1.8          matrixStats_0.61.0    vroom_1.5.7          
##  [25] R.utils_2.11.0        spatstat.sparse_2.1-0 rmdformats_1.0.3     
##  [28] colorspace_2.0-3      rvest_1.0.2           ggrepel_0.9.1        
##  [31] haven_2.4.3           xfun_0.29             crayon_1.5.0         
##  [34] jsonlite_1.7.2        spatstat.data_2.1-2   survival_3.2-11      
##  [37] zoo_1.8-9             iterators_1.0.14      glue_1.6.1           
##  [40] polyclip_1.10-0       gtable_0.3.0          leiden_0.3.9         
##  [43] future.apply_1.8.1    abind_1.4-5           scales_1.1.1         
##  [46] pheatmap_1.0.12       DBI_1.1.2             spatstat.random_2.1-0
##  [49] miniUI_0.1.1.1        riverplot_0.10        viridisLite_0.4.0    
##  [52] xtable_1.8-4          reticulate_1.24       spatstat.core_2.4-0  
##  [55] rsvd_1.0.5            mclust_5.4.9          bit_4.0.4            
##  [58] DT_0.20               htmlwidgets_1.5.4     httr_1.4.2           
##  [61] FNN_1.1.3             RColorBrewer_1.1-2    ellipsis_0.3.2       
##  [64] ica_1.0-2             farver_2.1.0          R.methodsS3_1.8.1    
##  [67] pkgconfig_2.0.3       sass_0.4.0            uwot_0.1.11          
##  [70] dbplyr_2.1.1          deldir_1.0-6          utf8_1.2.2           
##  [73] labeling_0.4.2        tidyselect_1.1.2      rlang_1.0.1          
##  [76] reshape2_1.4.4        later_1.3.0           munsell_0.5.0        
##  [79] cellranger_1.1.0      tools_4.1.1           cli_3.1.1            
##  [82] generics_0.1.2        broom_0.7.12          ggridges_0.5.3       
##  [85] evaluate_0.15         fastmap_1.1.0         yaml_2.3.5           
##  [88] goftest_1.2-3         bit64_4.0.5           knitr_1.37           
##  [91] fs_1.5.2              fitdistrplus_1.1-6    RANN_2.6.1           
##  [94] pbapply_1.5-0         future_1.24.0         nlme_3.1-152         
##  [97] mime_0.12             R.oo_1.24.0           xml2_1.3.3           
## [100] hdf5r_1.3.5           compiler_4.1.1        rstudioapi_0.13      
## [103] plotly_4.10.0         png_0.1-7             spatstat.utils_2.3-0 
## [106] reprex_2.0.1          bslib_0.3.1           stringi_1.7.6        
## [109] highr_0.9             RSpectra_0.16-0       lattice_0.20-44      
## [112] vctrs_0.3.8           pillar_1.7.0          lifecycle_1.0.1      
## [115] BiocManager_1.30.16   spatstat.geom_2.3-2   lmtest_0.9-39        
## [118] jquerylib_0.1.4       RcppAnnoy_0.0.19      data.table_1.14.2    
## [121] irlba_2.3.5           httpuv_1.6.5          R6_2.5.1             
## [124] bookdown_0.24         promises_1.2.0.1      KernSmooth_2.23-20   
## [127] gridExtra_2.3         parallelly_1.30.0     codetools_0.2-18     
## [130] MASS_7.3-54           assertthat_0.2.1      withr_2.5.0          
## [133] sctransform_0.3.3     mgcv_1.8-36           parallel_4.1.1       
## [136] hms_1.1.1             grid_4.1.1            rpart_4.1-15         
## [139] rmarkdown_2.11        Rtsne_0.15            shiny_1.7.1          
## [142] lubridate_1.8.0